/*

    tools23d - tools for converting images to 3D formats.
    Copyright (C) 2014  Dave Gorst

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

*/

/**
 * @file   cli-btime.c
 * @brief  Commandline option functions specific to btime23d.
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <time.h>

#include "tools23d.h"
#include "btime23d.h"
#include "cli-btime.h"
#include "cli-common.h"
#include "util.h"
#include "list.h"

option app_options_table [26] =
{
	{T3D_AppUnknown,NULL,NULL},        /* 'a'  */
    {T3D_AppUnknown,NULL,NULL},        /* 'b'  */
	{T3D_SetSine,"sinecurve",
		"Decide when images are displayed\n"
		"using a sine curve rather than their initial time.\n\n"
	},               /* 'c'  */
    {T3D_SetDirection,"direction",
		"Control the order frames are output.\n"
		"Valid values are forwards, backwards\n"
		"and bidirectional.\n\n"
	},          /* 'd'  */
    {T3D_AppUnknown,NULL,NULL},        /* 'e'  */
    {T3D_AppUnknown,NULL,NULL},        /* 'f'  */
    {T3D_AppUnknown,NULL,NULL},        /* 'g'  */
    {T3D_AppUnknown,NULL,NULL},        /* 'h'  */
    {T3D_AppUnknown,NULL,NULL},        /* 'i'  */
    {T3D_AppUnknown,NULL,NULL},        /* 'j'  */
    {T3D_AppUnknown,NULL,NULL},        /* 'k'  */
    {T3D_AppUnknown,NULL,NULL},        /* 'l'  */
    {T3D_AppUnknown,NULL,NULL},        /* 'm'  */
    {T3D_AppUnknown,NULL,NULL},        /* 'n'  */
    {T3D_AppUnknown,NULL,NULL},        /* 'o'  */
    {T3D_AppUnknown,NULL,NULL},        /* 'p'  */
    {T3D_AppUnknown,NULL,NULL},        /* 'q'  */
    {T3D_SetRepetitions,
		"repetitions",
		"Repeat the sequence of images one or more times.\n\n"
	},        /* 'r'  */
    {T3D_AppUnknown,NULL,NULL},        /* 's'  */
    {T3D_SetTimestretch,"timestretch",
		"Multiplier specifying how much longer or shorter\n"
		"the output should be compared to the input.\n\n"
	},    /* 't'  */
    {T3D_AppUnknown,NULL,NULL},        /* 'u'  */
    {T3D_AppUnknown,NULL,NULL},        /* 'v'  */
    {T3D_SetWraparound,"wraparound",
		"Instead of truncating frame set by the number of frames\n"
		"offset take frames from the opposite end of the set.\n\n"
	},     /* 'w'  */
    {T3D_AppUnknown,NULL,NULL},        /* 'x'  */
    {T3D_AppUnknown,NULL,NULL},        /* 'y'  */
    {T3D_AppUnknown,NULL,NULL}         /* 'z'  */
};

/**
Function called when the option is not a known common or btime23d specific option.
*/

OPTIONFUNCTION (T3D_AppUnknown)
{
	T3D_SetLastError ("Unknown command line option \"%c\".", input_char);

	return t3d_bad_parameter;
}

/**
Set flag indicating whether to use a sine value to display frames e.g. a +1.0 value = quick->slow->.quick.

@return	A ::t3d_return code indicating whether the option was set successfully.
*/

OPTIONFUNCTION (T3D_SetSine)
{
	if ((cli_params->sine = (float) atof (argv [*arg])) == ERANGE)
		return t3d_bad_parameter;
	++(*arg);

	return t3d_success;
}

/**
Specify the direction during repetitions.
Forward -> play all frames from 0000-XXXX every time.
Bidirectional -> play 0000-XXXX on the first frame then XXXX-0000 on the next.
Backwards -> Play all frames XXXX-0000 every time.

@return	A ::t3d_return code indicating whether the option was set successfully.
*/

OPTIONFUNCTION (T3D_SetDirection)
{
	if (strcmp (argv [*arg], "forwards") == 0)
		cli_params->direction = Forwards;
	else if (strcmp (argv [*arg], "backwards") == 0)
		cli_params->direction = Backwards;
	else if (strcmp (argv [*arg], "bidirectional") == 0)
		cli_params->direction = Bidirectional;
	else
	{
		T3D_SetLastError ("Unknown direction \"%s\" - valid values are forwards, backwards and bidirectional.", argv [*arg]);
		return t3d_bad_parameter;
	}
	++(*arg);

	return t3d_success;
}

/**
Specify how many times to iterate over the sequence of input images.

@return	A ::t3d_return code indicating whether the option was set successfully.
*/

OPTIONFUNCTION (T3D_SetRepetitions)
{
	cli_params->repetitions = atoi (argv [*arg]);
	if (cli_params->repetitions < 1)
	{
		T3D_SetLastError ("Sequence must be played at least once!");
		return t3d_bad_parameter;
	}
	++(*arg);

	return t3d_success;
}

/**
Set time stretch factor.

@return	A ::t3d_return code indicating whether the option was set successfully.
*/

OPTIONFUNCTION (T3D_SetTimestretch)
{
	if ((cli_params->time_stretch = (float) atof (argv [*arg])) == ERANGE)
		return t3d_bad_parameter;
	++(*arg);

	return t3d_success;
}

/**
Set flag indicating that we should grab files from the other end of the original frameset when
calculating which frame should be used for which eye.

@return	A ::t3d_return code indicating whether the option was set successfully.
*/

OPTIONFUNCTION (T3D_SetWraparound)
{
	cli_params->wraparound = TRUE;
	return t3d_success;
}

/**
Set btime23d specific default values.

@param	cli_params	Pointer to user options structure.
*/

void T3D_ClearAppParams (params * cli_params)
{
	cli_params->repetitions = 1;
	cli_params->frame_offset = 0;
	cli_params->sine = 0.0f;
	cli_params->time_stretch = 1.0f;
	cli_params->wraparound = FALSE;
	cli_params->direction = Forwards;

	cli_params->number_of_input_filenames = 0;
	cli_params->input_filenames = NULL;
}

/**
Free any memory allocated for btime23d parameters.

@param	my_params	Pointer to user options structure.
*/

void T3D_FreeAppParams (params * my_params)
{
	if (my_params->input_filenames != NULL) free (my_params->input_filenames);
}

/**
Set any btime23d-specific default application parameters.

@param	my_params	Pointer to user options structure.
*/

void T3D_SetAppDefaults (params * my_params)
{
    /* None at present */
}

/**
Handle btime23d fixed args (currently 3 required).

@param  cli_params  Pointer to user options structure.
@param  number_of_args  Number of arguments.
@param  arglist Pointer to list of arguments.
@return ::TRUE if sucessful, ::FALSE otherwise.
*/

BOOL T3D_HandleFixedArgs (params * cli_params, unsigned int number_of_args, char ** arglist)
{
	unsigned int arg;
	char * current_arg;
	BOOL success = TRUE;

	if (number_of_args < 3)
	{
		T3D_SetLastError ("Not enough arguments supplied.");
		return FALSE;
	}

	for (arg = 0; ((arg < number_of_args) && (success)); arg++)
	{
		current_arg = arglist [arg];

		if (!arg)
		{
			/* Frame offset parameter */
			if (!T3D_IsNumeric (current_arg))
			{
				T3D_SetLastError ("Non-numeric digit found in frame offset.");
				return FALSE;
			}
			/* Set frame offset between left and right panes e.g. if 4
				is passed the right pane will be 4 frames ahead, for use
				during rightwards camera pans. */

			cli_params->frame_offset = atoi (current_arg);

			if (!cli_params->frame_offset)
				success = T3D_RaiseWarning
				(
						&cli_params->always_yes,
						"Setting an offset of zero is probably extremely pointless."
				);
		}
		else if (arg == number_of_args - 1)
		{
			/* Specify output file pattern e.g. img-%03d.jpg */
			cli_params->output_filename = current_arg;
		}
		else
		{
			/* Specify input file pattern e.g. files????.png */
			cli_params->input_filenames = T3D_AddToList ((unsigned int *) &(cli_params->number_of_input_filenames), cli_params->input_filenames, current_arg);
		}
	}

	return success;
}

void T3D_PrintBanner (void)
{
	(void) fprintf (stdout,
		"\nbtime23d  Copyright (C) 2014 Dave Gorst\n"
		"=======================================\n\n"
		"This program comes with ABSOLUTELY NO WARRANTY.\n"
		"This is free software, and you are welcome to redistribute it\n"
		"under certain conditions.\n\n"
	);
}

void T3D_PrintHeader (void)
{
	T3D_OutputMessage
	(
		"Syntax : btime23d <offset> <input filenames> <output path/filename> [options]\n"
		"\nValid options are :\n\n"
	);
}

